package newcall.com.newcalldemo;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.Log;

import com.m800.m800demo.R;
import com.m800.sdk.M800ApplicationPlatform;
import com.m800.sdk.M800SDK;
import com.m800.sdk.M800SDKConfiguration;
import com.m800.sdk.call.CallLogLevels;
import com.m800.sdk.call.M800CallConfiguration;
import com.m800.sdk.call.M800CallSessionManager;
import com.m800.uikit.M800UIKitManager;
import com.m800.verification.LogLevels;
import com.m800.verification.M800VerificationClient;
import com.m800.verification.M800VerificationConfiguration;
import com.m800.verification.M800VerificationManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;

public class InitM800SDKTask extends AsyncTask<Void, Void, Boolean> {

    Context mContext;
    final static  String DEBUG_TAG="test";
    private static final String PREF_M800_CERT = "com.demo.m800.cert";
    private static final String PREF_M800_CALL_HOLD_TONE = "com.demo.m800.call.hold_tone";
    private static final String PREF_M800_CALL_RING_BACK_TONE = "com.demo.m800.call.ring_back_tone";
    private static final String PREF_M800_CALL_RING_TONE = "com.demo.m800.call.ring_tone";
    private File mCertFile;
    private File mHoldToneFile;
    private File mRingBackToneFile;
    private File mRingToneFile;


    public InitM800SDKTask(Context context) {
        this.mContext = context;
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        if (!M800SDK.isInitialized()) {
            initM800SDk(mContext, isTablet());
            initM800SDKCall();
            M800UIKitManager.initialize(mContext);
            return true;
        }
        return false;


    }

    private void initM800SDk(Context mContext, boolean tablet) {
        // Configure M800SDK
        M800SDKConfiguration.Builder builderConfig = new
                M800SDKConfiguration.Builder();
        builderConfig.setApplicationContext(mContext.getApplicationContext());
        Resources resources = mContext.getResources();
// Provide correct platform's keys
        if (tablet) {
            builderConfig.setApplicationKey(resources.getString(R.string.M800DefaultTabletApplicationKey))
                    .setApplicationSecret(resources.getString(R.string.M800DefaultTabletApplicationSecret))
                    .setApplicationPlatform(M800ApplicationPlatform.AndroidTablet);
        } else {
            builderConfig.setApplicationKey(resources.getString(R.string.M800DefaultPhoneApplicationKey))
                    .setApplicationSecret(resources.getString(R.string.M800DefaultPhoneApplicationSecret))
                    .setApplicationPlatform(M800ApplicationPlatform.AndroidPhone);
        }
        builderConfig.setApplicationIdentifier(resources.getString(R.string.M800DefaultApplicationIdentifier))
                .setApplicationVersion(resources.getString(R.string.M800DefaultApplicationVersion))
                .setDeveloperKey(resources.getString(R.string.M800DefaultDeveloperKey))
                .setCarrier(resources.getString(R.string.M800DefaultCarrier))
                .setCapabilities(resources.getString(R.string.M800DefaultCapabilities))
                .setExpiration(resources.getString(R.string.M800DefaultExperation))
                .setCertificateForIM(resources.getString(R.string.M800IMCert))
                .setHTTPSignupHosts(resources.getStringArray(R.array.M800HTTPSignupHosts))
                .setSavingCallLogEnabled(true)
                .setSavingConferenceCallLogEnabled(true)
                .setCountingUnreadControlMessageEnabled(false);
        M800SDKConfiguration configuration = builderConfig.build();

        //Initialize verification sdk
        initializeVerificationSDK(configuration);


        M800SDK.setConfiguration(configuration);
     // Init M800SDK on a worker thread
        M800SDK.initialize();


    }

    private void initializeVerificationSDK(M800SDKConfiguration m800Config) {
        Resources resources = mContext.getResources();

        // Get dev secret
        String devSecret = resources.getString(R.string.M800DefaultDeveloperSecret);
        // Get verification service hosts
        String[] verificationHosts = resources.getStringArray(R.array.M800DefaultVerificationHosts);
        // Set configuration
        M800VerificationConfiguration.Builder confBuilder =
                new M800VerificationConfiguration.Builder()
                        .applicationKey(m800Config.getApplicationKey())
                        .appSecret(m800Config.getApplicationSecret())
                        .developerKey(m800Config.getDeveloperKey())
                        .devSecret(devSecret)
                        .hosts(new ArrayList<>(Arrays.asList(verificationHosts)));
        M800VerificationClient.setLogLevel(LogLevels.DEBUG);
        M800VerificationManager verificationManager = M800VerificationClient
                .getVerificationManager(mContext.getApplicationContext());
        verificationManager.setConfiguration(confBuilder.build());
        // Start to load phone number information
        verificationManager.loadPhoneNumberInfo();
    }
    private void initM800SDKCall() {
        if (mCertFile == null) {
            mCertFile = copyCertificateFromAsset();
        }
        if (mHoldToneFile == null) {
            mHoldToneFile = copyHoldToneFromAsset();
        }
        if (mRingBackToneFile == null) {
            mRingBackToneFile = copyRingBackToneFromAsset();
        }
        if (mRingToneFile == null) {
            mRingToneFile = copyRingToneFromAsset();
        }

        M800CallConfiguration config = new M800CallConfiguration.Builder()
                .certificate(mCertFile)
                .holdTone(mHoldToneFile)
                .ringbackTone(mRingBackToneFile)
                .ringTone(mRingToneFile)
                .setSupportAutoReconfiguration(true)
                .build();

        M800CallSessionManager.setLogLevel(CallLogLevels.DEBUG);
        M800CallSessionManager.init(mContext.getApplicationContext(), config);
    }


    private boolean isTablet() {
        DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
        int width = dm.widthPixels;
        int height = dm.heightPixels;
        int dens = dm.densityDpi;
        double wi = (double) width / (double) dens;
        double hi = (double) height / (double) dens;
        double x = Math.pow(wi, 2);
        double y = Math.pow(hi, 2);
        double diagonalInches = Math.sqrt(x + y);
        boolean nexus7 = Build.MODEL.equalsIgnoreCase("nexus 7");

        // For devices that has diagonal inches greater than 7, we treat it as tablet
        return diagonalInches > 7 || nexus7;
    }

    private File copyCertificateFromAsset() {
        String assetFileName = "cacert.crt";
        File certFile = copyFileFromAsset(assetFileName);
        if (certFile != null) {
            Log.d(DEBUG_TAG, "M800 cert file: " + certFile.getAbsolutePath());
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
            SharedPreferences.Editor editor = sp.edit();
            editor.putString(PREF_M800_CERT, certFile.getAbsolutePath());
            editor.apply();
        }
        return certFile;
    }

    private File copyHoldToneFromAsset() {
        String assetFileName = "hold_tone.raw";
        File holdToneFile = copyFileFromAsset(assetFileName);
        if (holdToneFile != null) {
            Log.d(DEBUG_TAG, "M800 call hold tone file: " + holdToneFile.getAbsolutePath());
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
            SharedPreferences.Editor editor = sp.edit();
            editor.putString(PREF_M800_CALL_HOLD_TONE, holdToneFile.getAbsolutePath());
            editor.apply();
        }
        return holdToneFile;
    }

    private File copyRingBackToneFromAsset() {
        String assetFileName = "bell_ringback.raw";
        File ringBackToneFile = copyFileFromAsset(assetFileName);
        if (ringBackToneFile != null) {
            Log.d(DEBUG_TAG, "M800 call ring back tone file: " + ringBackToneFile.getAbsolutePath());
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
            SharedPreferences.Editor editor = sp.edit();
            editor.putString(PREF_M800_CALL_RING_BACK_TONE, ringBackToneFile.getAbsolutePath());
            editor.apply();
        }
        return ringBackToneFile;
    }

    private File copyRingToneFromAsset() {
        String assetFileName = "incoming_call.mp3";
        File ringToneFile = copyFileFromAsset(assetFileName);
        if (ringToneFile != null) {
            Log.d(DEBUG_TAG, "M800 call ring tone file: " + ringToneFile.getAbsolutePath());
            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
            SharedPreferences.Editor editor = sp.edit();
            editor.putString(PREF_M800_CALL_RING_TONE, ringToneFile.getAbsolutePath());
            editor.apply();
        }
        return ringToneFile;
    }
    private File copyFileFromAsset(String filename) {
        AssetManager am = mContext.getAssets();
        InputStream in;
        OutputStream out;
        try {
            in = am.open(filename);
            String cacheDir = mContext.getFilesDir().getAbsolutePath();
            File outFile = new File(cacheDir, filename);
            out = new FileOutputStream(outFile);

            byte[] buffer = new byte[1024];
            int read;
            while ((read = in.read(buffer)) != -1) {
                out.write(buffer, 0, read);
            }

            in.close();
            out.flush();
            out.close();

            return outFile;
        } catch (IOException e) {
            Log.e(DEBUG_TAG, "Failed to copy file from asset!", e);
        }
        return null;
    }
}
